/*
 * Author: vdaras
 */

#ifndef CONTAINER_H
#define	CONTAINER_H

#include "Component.h"
#include <list>


namespace gui
{


/**
 * This class contains other components and is responsible to draw and to
 * update them. It acts as a composite of the Composite pattern, since a cointainer
 * can contain other containers.
 */

class Container : public Component
{
    friend Component* FocusServer::ResolveMouseFocus(const MouseEvent& event, gui::Container *root);
    
private:
    std::list< Component* > m_components;

public:

    /**
     * Constructor initializes the parent class of the Container, its position
     * and dimension.
     *
     * @param parent: Container's parent Component in the Composite tree
     * @param name: Container's name
     * @param w: Container's width
     * @param h: Container's height
     */

    Container(const std::string &name, int x, int y, int w, int h);


    /**
     * Constructor initializes the parent class of the Container, its position
     * and dimension. It also makes this Container a part of another Container.
     *
     * @param parent: Container's parent Component in the Composite tree
     * @param name: Container's name
     * @param w: Container's width
     * @param h: Container's height
     */

    Container(const std::string &name, Container *parent, int x, int y, int w, int h);


    /**
     * Destructor frees all contained Components.
     */

    virtual ~Container();
    
    
    /**
     * Resizes this Container.
     *
     * @param width: new width.
     * @param height: new height.
     */
    
    virtual void Resize(int width, int height);

    
    /**
     * This routine adds a component to the container's list. IMPORTANT, the container
     * now retains ownership of the component, thus is responsible for the component's
     * memory management.
     *
     * @param toAdd: the component to add
     */

    void AddComponent(Component *toAdd);


    /**
     * This routine adds a component to the container's list. It also places
     * the component on the provided coordinates inside the container. IMPORTANT,
     * the container now retains ownership of the component, thus is responsible for
     * the component's memory management.
     *
     * @param toAdd: the component to add
     * @param x: desired x in container
     * @param y: desired y in container
     */

    void AddComponent(Component *toAdd, int x, int y);


    /**
     * This routine brings the specified Component to the front.
     *
     * @param comp: component to bring to the front
     */

    void BringToFront(Component *comp);


    /**
     * This routine removes a component from the Container's list. IMPORTANT, the client
     * code is responsible for the component's memory management now!
     *
     * @param toRemove: the component to Remove
     */

    void RemoveComponent(Component *toRemove);


    /**
     * This routine finds a component in the current container based on it's name
     * identifier. Returns null if it doesn't exist.
     *
     * @param name: the name of the component we wish to search for
     */

    Component *FindComponent(const std::string &name);


    /**
     * This routine draws each component in the component's list
     *
     * @param target: surface to draw the components on
     */

    virtual void Draw(sdl::Surface *target) const;

    
    /**
     * Forwards the mouse event to all its components.
     *
     * @param event: a mouse event occurred.
     */
    
    virtual void OnMouseEvent(MouseEvent& event);
    
    
    /**
     * Returns a pointer to this Container object. Used to provide run time information
     * on the Composite structure. See Composite pattern.
     */
    
    virtual Container *GetContainer();
    
    
    /**
     * Clears all Components belonging to this Container. 
     */
    
    void Clear();
};

};

#endif	/* CONTAINER_H */

